/*******************************************************************************
 * Copyright (c) 2011 Jovansonlee B. Cesar.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Jovansonlee B. Cesar - initial API and implementation
 ******************************************************************************/
package com.ivanceras.server.services;

import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap;

import net.sf.jsr107cache.Cache;
import net.sf.jsr107cache.CacheException;
import net.sf.jsr107cache.CacheFactory;
import net.sf.jsr107cache.CacheManager;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.ivanceras.client.DataService;
import com.ivanceras.shared.bo.Ad_column;
import com.ivanceras.shared.bo.Ad_tab;
import com.ivanceras.shared.bo.Ad_table;
import com.ivanceras.shared.bo.Ad_window;
import com.ivanceras.shared.dao.DAO_Ad_column;
import com.ivanceras.shared.dao.DAO_Ad_tab;
import com.ivanceras.shared.dao.DAO_Ad_table;
import com.ivanceras.shared.dao.DAO_Ad_window;
import com.ivanceras.shared.db.DAO;
import com.ivanceras.shared.db.EMF;
import com.ivanceras.shared.db.EntityManager;
import com.ivanceras.shared.db.Order;
import com.ivanceras.shared.db.SerializableDAO;
import com.ivanceras.shared.db.SerializableFilter;
import com.ivanceras.shared.exception.DatabaseException;
import com.ivanceras.shared.exception.IvancerasServiceException;
import com.ivanceras.shared.mapper.Ad_columnMapper;
import com.ivanceras.shared.mapper.Ad_tabMapper;
import com.ivanceras.shared.mapper.Ad_tableMapper;
import com.ivanceras.shared.mapper.Ad_windowMapper;
import com.ivanceras.shared.util.Configuration;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class DataServiceImpl extends RemoteServiceServlet implements
DataService {

	@Override
	public Ad_window[] retrieveWindowList() throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_window[] daoWindowList = DataAPI.retrieveWindowList(em);
			return Ad_windowMapper.map(daoWindowList);
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			if(em != null){
				em.close();
			}
		}
	}

	@Override
	public Ad_tab[] retriveTabList(Ad_window window) throws IvancerasServiceException {
		return retriveTabList(window, Configuration.enableCache);
	}
	public Ad_tab[] retriveTabList(Ad_window window, Boolean useCache) throws IvancerasServiceException {
	    Cache cache = null;
	    if(useCache){
	        try {
	            CacheFactory cacheFactory = CacheManager.getInstance().getCacheFactory();
	            cache = cacheFactory.createCache(Collections.emptyMap());
	            if(cache != null && cache.containsKey(window.getAd_window_id())){
	            	return	(Ad_tab[])cache.get(window.getAd_window_id());
	            }else if(cache == null){
		        	System.err.println("Cache is not available...");
	            }
	        } catch (CacheException e) {
            	System.err.println("Cache is not available...");
	        	e.printStackTrace();
	        } 
		}
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_window daoWindow = new DAO_Ad_window();
			daoWindow.setAd_window_id(window.getAd_window_id());
			DAO_Ad_tab[] tabList = DataAPI.retriveTabList(em, daoWindow);
			Ad_tab[] adtabList = null;
			if(tabList != null){
				adtabList = Ad_tabMapper.map(tabList);
				if(useCache && cache != null){
					System.out.println("trying to put to cache: "+cache);
					System.out.println("This window: "+window);
					cache.put(window.getAd_window_id(), adtabList);
				}
				return adtabList;
			}
			else{
				return null;
			}
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}

	@Override
	public SerializableDAO[] retrieveTableData(Ad_table table, Integer page, Integer itemPerPage,
			Order order, SerializableFilter sfilter) throws IvancerasServiceException {
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_table daoTable = Ad_tableMapper.map(table);
			DAO[] rdaoList = DataAPI.retrieveTableData(em, daoTable, page, itemPerPage, order, SerializableFilter.cast(sfilter));
			SerializableDAO[] daoList = SerializableDAO.cast(rdaoList);
			return daoList;
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}

	/**
	 * Retrieve the table data on this table basing from the parent table as the filter
	 * @param parent
	 * @param table
	 * @param page
	 * @param itemPerPage
	 * @param order
	 * @param sfilter
	 * @return
	 * @throws IvancerasServiceException
	 */
	@Override
	public SerializableDAO[] retrieveChrildrenTableData(Ad_table parent, Ad_table table, Integer page, Integer itemPerPage,
			Order order, SerializableFilter sfilter) throws IvancerasServiceException {
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_table daoTable = Ad_tableMapper.map(table);
			DAO_Ad_table daoParent = Ad_tableMapper.map(parent);
			DAO[] rdaoList = DataAPI.retrieveChildrenTableData(em, daoParent, daoTable, page, itemPerPage, order, SerializableFilter.cast(sfilter));
			SerializableDAO[] daoList = SerializableDAO.cast(rdaoList);
			return daoList;
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
	}

	@Override
	public Boolean importDaoXmlFromUrl(String httpurl) throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DataAPI.importDAO(em, httpurl);
			return true;
		} catch (DatabaseException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("SQL exception");
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("XML is malformed");
		}
		finally{
			if(em != null)
			em.close();
		}
	}
	
	@Override
	public HashMap<String, Integer> getTableList(String xmlurl) throws IvancerasServiceException{
		try {
			return DataAPI.parseTableListXml(xmlurl);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new IvancerasServiceException("XML is malformed");
		}
	}
	
	public Boolean saveDao(SerializableDAO[] s_daoList) throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DataAPI.saveDao(em, SerializableDAO.cast(s_daoList));
			return true;
		} catch (DatabaseException e1) {
			e1.printStackTrace();
			throw new IvancerasServiceException();
		}
		finally{
			em.close();
		}
		
	}
	
	@Override
	public HashMap<String, String> retrieveListData(Ad_column column) throws IvancerasServiceException{
		EntityManager em = null;
		try {
			em = EMF.get();
			DAO_Ad_column daoColumn = Ad_columnMapper.map(column);
			return DataAPI.retrieveListData(em, daoColumn);
		} catch (DatabaseException e) {
			e.printStackTrace();
			throw new IvancerasServiceException();
		}finally{
			em.close();
		}
	}

	@Override
	public String retrieveDataName(Ad_column column, String value) throws IvancerasServiceException {
		EntityManager em = null;
		try{
			em = EMF.get();
			DAO_Ad_column daoColumn = Ad_columnMapper.map(column);
			return DataAPI.retrieveDataName(em, daoColumn, value);
		}catch(DatabaseException e){
			e.printStackTrace();
			throw new IvancerasServiceException();
		}finally{
			em.close();
		}
	}

}
